#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cassert>
#include <jsoncpp/json/json.h>

#define CRLF "\r\n"
#define CRLF_LEN strlen(CRLF)
#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define OPS "+-*/%"
// #define MY_SELF 1

// 解码 9\r\n100 + 200\r\n    9\r\n112 / 200\r\n
static std::string decode(std::string &in, uint32_t *len)
{
    assert(len);
    // 1. 确认是否是一个包含len的有效字符串
    *len = 0;
    std::size_t pos = in.find(CRLF); // 报头长度
    if (pos == std::string::npos)
    {
        return "";
    }
    // 2. 提取长度
    std::string inLen = in.substr(0, pos);
    int intLen = atoi(inLen.c_str()); // 报头值
    // 3. 确认有效载荷也是符合要求的
    int surplus = in.size() - (pos + CRLF_LEN * 2);
    if (surplus < intLen)
    {
        return "";
    }
    // 4. 确认有完整的报文结构
    *len = intLen;
    std::string package = in.substr(pos + CRLF_LEN, intLen);
    // 5. 将当前报文完整的从in中全部移除掉
    int removeLen = pos + CRLF_LEN * 2 + intLen;
    in.erase(0, removeLen);
    // 6. 正常返回
    return package;
}
// 加码
static std::string encode(std::string &in, size_t len)
{
    std::string encodein = std::to_string(len);
    encodein += CRLF;
    encodein += in;
    encodein += CRLF;
    return encodein;
}

// 9\r\n100 + 200\r\n    9\r\n112 / 200\r\n
class Request
{
public:
    // 反序列化 100 + 200 字符串 转 结构体
    bool deserialize(std::string &in)
    {
#ifdef MY_SELF
        size_t SpaceOne = in.find(SPACE);
        if (SpaceOne == std::string::npos)
            return false;
        size_t SpaceTwo = in.rfind(SPACE);
        if (SpaceTwo == std::string::npos)
            return false;
        x_ = atoi((in.substr(0, SpaceOne)).c_str());
        y_ = atoi((in.substr(SpaceTwo + SPACE_LEN)).c_str());
        std::string oper = in.substr(SpaceOne + SPACE_LEN, SpaceTwo - SpaceOne - SPACE_LEN);
        if (oper.size() != 1)
            return false;
        op_ = oper[0];
        return true;
#else
        Json::Value root;
        Json::Reader rd;
        rd.parse(in,root);
        x_=root["x"].asInt();
        y_=root["y"].asInt();
        op_=root["op"].asInt();
        return true;
#endif
    }
    // 序列化， 结构体 转 字符串 "1 + 1"
    void serialize(std::string &out)
    {
#ifdef MY_SELF
        out += std::to_string(x_);
        out += SPACE;
        out += op_;
        out += SPACE;
        out += std::to_string(y_);
        std::cout << "out: " << out << std::endl;
#else
        Json::Value root;
        root["x"] = x_;
        root["y"] = y_;
        root["op"] = op_;
        Json::FastWriter fw;
        out=fw.write(root);
#endif
    }
    void debug()
    {
        std::cout << "#################################" << std::endl;
        std::cout << "x_: " << x_ << std::endl;
        std::cout << "op_: " << op_ << std::endl;
        std::cout << "y_: " << y_ << std::endl;
        std::cout << "#################################" << std::endl;
    }
    // private:
    int x_;
    int y_;
    char op_;
};

class Respond
{
public:
    Respond() : exitCode_(0), result_(0)
    {
    }
    // 序列化， 结构体 转 字符串 res.serialize(&respPackage);
    void serialize(std::string *out)
    {
#ifdef MY_SELF
        *out = std::to_string(exitCode_);
        *out += SPACE;
        *out += std::to_string(result_);
#else
        Json::Value root;
        root["exitCode"]=exitCode_;
        root["result"]=result_;
        Json::FastWriter fw;
        *out=fw.write(root);
#endif 
    }
    bool deserialize(std::string &in)
    {
#ifdef MY_SELF
        size_t pos = in.find(SPACE);
        if (pos == std::string::npos)
            return false;
        exitCode_ = atoi((in.substr(0, pos)).c_str());
        result_ = atoi((in.substr(pos + 1)).c_str());
        return true;
#else
        Json::Value root;
        Json::Reader rd;
        rd.parse(in,root);
        exitCode_=root["exitCode"].asInt();
        result_=root["result"].asInt();
        return true;
#endif
    }
    int exitCode_;
    int result_;
};

// 1+1 strtmp
bool makeRequest(std::string &str, Request *req)
{
    char strtmp[1024];
    snprintf(strtmp, sizeof(strtmp) - 1, "%s", str.c_str());
    char *left = strtok(strtmp, OPS);
    if (left == nullptr)
        return false;
    char *right = strtok(nullptr, OPS);
    if (right == nullptr)
        return false;
    req->x_ = atoi(left);
    req->y_ = atoi(right);
    req->op_ = str[strlen(left)];
    return true;
}